home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 21
/
CU Amiga Magazine's Super CD-ROM 21 (1998)(EMAP Images)(GB)[!][issue 1998-04].iso
/
CUCD
/
Programming
/
RTGMaster
/
demos
/
moon
/
WORLD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-05
|
19KB
|
650 lines
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include "random.h"
#include "world.h"
#define _MAKE_CRATERS
#define _USE_ROUGHNESS_MAP
//#define _BIZARRE_ROUGHNESS_MAP
//#define _BIZARRE_ALT_MAP
//#define DEBUG
//----------------------------------------------------------------------------
// The maps. Note that, in this module, the color_map array is used during
// the generation of the altitude map, so in that case, it is misnamed.
//----------------------------------------------------------------------------
map_t far alt_map;
map_t far color_map;
//----------------------------------------------------------------------------
// An internal temporary map used in generating the other maps:
//----------------------------------------------------------------------------
static map_t temp_map;
//----------------------------------------------------------------------------
// Assertion code for this module:
//----------------------------------------------------------------------------
#ifdef DEBUG
static void _Assert
(
const char * file,
unsigned line,
const char * assertion
)
{
fflush (stdout);
fprintf ( stderr, "\nAssertion failed (%s, line %u): %s\n",
file, line, assertion );
fflush (stderr);
abort ();
}
#define ASSERT(f) if (f) {} else _Assert ( __FILE__, __LINE__, #f )
#else
#define ASSERT(f)
#endif
//----------------------------------------------------------------------------
// FUNCTION rough_init
//----------------------------------------------------------------------------
#ifdef _USE_ROUGHNESS_MAP
static void rough_init
(
void
)
{
int x, y;
for ( x = 0; x < map_size_x; x += 64 )
{
for ( y = 0; y < map_size_y; y += 64 )
{
color_map [x][y] = (unsigned char) (random ( 128 ) + 80);
}
}
}
#endif
//----------------------------------------------------------------------------
// FUNCTION map_init
//----------------------------------------------------------------------------
static void map_init
(
void
)
{
int x, y;
for ( x = 0; x < map_size_x; x += 64 )
{
for ( y = 0; y < map_size_y; y += 64 )
{
color_map [x][y] = (unsigned char) random ( 256 );
}
}
}
//----------------------------------------------------------------------------
// FUNCTION flat_area
//----------------------------------------------------------------------------
static void flat_area(
int map_x,
int map_y,
int size_x,
int size_y,
int height_offset/* = 0 */
)
{
int height;
int x, y;
// First get the average height of the original rectangular region.
height = 0;
for ( x = 0; x < size_x; ++ x ){
for ( y = 0; y < size_y; ++ y ){
height +=
(int) alt_map [(x+map_x) & clip_mask_x][(y+map_y) & clip_mask_y];
}
}
height /= size_x * size_y;
// Offset from the average height.
height += height_offset;
if ( height < min_alt ) height = min_alt;
else if ( height > max_alt-1 ) height = max_alt - 1;
// Put in the landing pad.
for ( x = 0; x < size_x; ++ x ){
for ( y = 0; y < size_y; ++ y ){
alt_map [(x+map_x) & clip_mask_x][(y+map_y) & clip_mask_y] =
(unsigned char) (height + random (2));
}
}
}
//----------------------------------------------------------------------------
// FUNCTION quonset_hut
//----------------------------------------------------------------------------
// These quonset huts run parallel to the Y axis.
//----------------------------------------------------------------------------
static void quonset_hut
(
int map_x,
int map_y,
int size_y
)
{
int average;
int x, y;
int r_squared;
const radius = 4;
// First get the average height of the original region.
average = 0;
for ( x = 0; x < radius * 2; ++ x ){
for ( y = 0; y < size_y; ++ y ){
average +=alt_map [(x+map_x) & clip_mask_x][(y+map_y) & clip_mask_y];
}
}
average /= size_y * radius * 2;
// Bury the quonset hut a bit.
average -= scale_area / scale_height;
// Build the hut.
r_squared = radius * radius;
for ( x = 0; x < radius * 2; ++ x ){
int height =
(int) sqrt ( (double) (r_squared - (x-radius)*(x-radius) + 1) );
height *= (scale_area / scale_height);
height += average;
if ( height > max_alt ) height = max_alt;
for ( y = 0; y < size_y; ++ y ){
alt_map [(x+map_x) & clip_mask_x][(y+map_y) & clip_mask_y] =(unsigned char) height;
}
}
}
//----------------------------------------------------------------------------
// FUNCTION generate_roughness_map
//----------------------------------------------------------------------------
#ifdef _USE_ROUGHNESS_MAP
static void generate_roughness_map(void)
{
int counter = 0;
int which = 0;
int square_size,x1,y1;
printf ( " Roughness map: 0 %%" );
rough_init ();
for ( square_size = 64; square_size > 1; square_size /= 2 ){
for ( x1 = 0; x1 < map_size_x; x1 += square_size ) {
for ( y1 = 0; y1 < map_size_y; y1 += square_size ) {
// Get the four influential points.
int x2 = (x1 + square_size) & clip_mask_x;
int y2 = (y1 + square_size) & clip_mask_y;
int i1, i2, i3, i4;
int p1,p2,p3,p4;
int random_center,random_range;
if ( which == 0 )
{
i1 = color_map [x1][y1];
i2 = color_map [x2][y1];
i3 = color_map [x1][y2];
i4 = color_map [x2][y2];
}else{
i1 = alt_map [x1][y1];
i2 = alt_map [x2][y1];
i3 = alt_map [x1][y2];
i4 = alt_map [x2][y2];
}
// Obtain new points by averaging the influential points.
p1 = ((i1 * 9) + (i2 * 3) + (i3 * 3) + (i4)) / 16;
p2 = ((i1 * 3) + (i2 * 9) + (i3) + (i4 * 3)) / 16;
p3 = ((i1 * 3) + (i2) + (i3 * 9) + (i4 * 3)) / 16;
p4 = ((i1) + (i2 * 3) + (i3 * 3) + (i4 * 9)) / 16;
// Add a random offset to each new point.
random_center = square_size;
random_range = random_center * 2;
#ifdef _BIZARRE_ROUGHNESS_MAP
p1 += random (random_center) + random_range - (max_alt - p1)/6;
p2 += random (random_center) + random_range - (max_alt - p2)/6;
p3 += random (random_center) + random_range - (max_alt - p3)/6;
p4 += random (random_center) + random_range - (max_alt - p4)/6;
#else
p1 += random (random_range) - random_center;
p2 += random (random_range) - random_center;
p3 += random (random_range) - random_center;
p4 += random (random_range) - random_center;
#endif
// Boundary check the altitudes. Under the normal condition,
// altitudes that are out of range will be "reflected" back into
// the allowable range. Under the bizarre condition, we do
// something bizarre!
#ifdef _BIZARRE_ROUGHNESS_MAP
p1 = (p1 < min_alt) ? max_alt + p1 + 1 : p1;
p2 = (p2 < min_alt) ? max_alt + p2 + 1 : p2;
p3 = (p3 < min_alt) ? max_alt + p3 + 1 : p3;
p4 = (p4 < min_alt) ? max_alt + p4 + 1 : p4;
p1 = (p1 > max_alt) ? (p1 % (max_alt+1)) : p1;
p2 = (p2 > max_alt) ? (p2 % (max_alt+1)) : p2;
p3 = (p3 > max_alt) ? (p3 % (max_alt+1)) : p3;
p4 = (p4 > max_alt) ? (p4 % (max_alt+1)) : p4;
#else
p1 = (p1 < min_alt) ? (min_alt - p1) + min_alt : p1;
p2 = (p2 < min_alt) ? (min_alt - p2) + min_alt : p2;
p3 = (p3 < min_alt) ? (min_alt - p3) + min_alt : p3;
p4 = (p4 < min_alt) ? (min_alt - p4) + min_alt : p4;
p1 = (p1 > max_alt) ? (max_alt - p1) + max_alt : p1;
p2 = (p2 > max_alt) ? (max_alt - p2) + max_alt : p2;
p3 = (p3 > max_alt) ? (max_alt - p3) + max_alt : p3;
p4 = (p4 > max_alt) ? (max_alt - p4) + max_alt : p4;
#endif
// Write out the generated points.
x2 = (x1 + square_size/2) & clip_mask_x;
y2 = (y1 + square_size/2) & clip_mask_y;
if ( which == 0 ){
alt_map [x1][y1] = (unsigned char) p1;
alt_map [x2][y1] = (unsigned char) p2;
alt_map [x1][y2] = (unsigned char) p3;
alt_map [x2][y2] = (unsigned char) p4;
}else {
color_map [x1][y1] = (unsigned char) p1;
color_map [x2][y1] = (unsigned char) p2;
color_map [x1][y2] = (unsigned char) p3;
color_map [x2][y2] = (unsigned char) p4;
}
counter += 100;
}
{
int percent_done = (int) ( counter / 87360 );
printf ( "\b\b\b\b\b%3d %%", percent_done );
}
}
which = (which == 0) ? 1 : 0;
}
if ( which == 0 ){
memcpy ( temp_map, color_map, sizeof (temp_map) );
}else{
memcpy ( temp_map, alt_map, sizeof (temp_map) );
}
printf ( "\b\b\b\b\bdone \n" );
}
#endif
//----------------------------------------------------------------------------
// FUNCTION generate_alt_map
//----------------------------------------------------------------------------
static void generate_alt_map(void)
{
int which = 0;
int counter = 0;
int square_size,i,x,y,x1,y1;
#ifdef _USE_ROUGHNESS_MAP
generate_roughness_map ();
#endif
printf ( " Altitude map: 0 %%" );
fflush ( stdout );
map_init ();
for ( square_size = 64; square_size > 1; square_size /= 2 ){
#ifdef _MAKE_CRATERS
if ( square_size == 8 || square_size == 4 ){
for ( i = 0; i < map_size_x * 3; ++ i ){
if ( which == 0 )
color_map [random (map_size_x)][random (map_size_y)]
= (unsigned char) random (32);
else
alt_map [random (map_size_x)][random (map_size_y)]
= (unsigned char) random (32);
}
}
#endif
// Make pseudo-valley floors.
if ( square_size == 2 ){
for ( x = 0; x < map_size_x; ++ x ){
for ( y = 0; y < map_size_y; ++ y ){
const cutoff_point = (max_alt+1) / 4;
if ( alt_map [x][y] < cutoff_point ){
alt_map [x][y] = (unsigned char) (cutoff_point - alt_map [x][y]/2);
}
}
}
}
for ( x1 = 0; x1 < map_size_x; x1 += square_size ) {
for ( y1 = 0; y1 < map_size_y; y1 += square_size ){
// Get the four influential points.
int x2 = (x1 + square_size) & clip_mask_x;
int y2 = (y1 + square_size) & clip_mask_y;
int i1, i2, i3, i4;
int p1,p2,p3,p4;
int random_center,random_range;
if ( which == 0 ){
i1 = color_map [x1][y1];
i2 = color_map [x2][y1];
i3 = color_map [x1][y2];
i4 = color_map [x2][y2];
} else {
i1 = alt_map [x1][y1];
i2 = alt_map [x2][y1];
i3 = alt_map [x1][y2];
i4 = alt_map [x2][y2];
}
// Obtain new points by averaging the influential points.
p1 = ((i1 * 9) + (i2 * 3) + (i3 * 3) + (i4)) / 16;
p2 = ((i1 * 3) + (i2 * 9) + (i3) + (i4 * 3)) / 16;
p3 = ((i1 * 3) + (i2) + (i3 * 9) + (i4 * 3)) / 16;
p4 = ((i1) + (i2 * 3) + (i3 * 3) + (i4 * 9)) / 16;
// Add a random offset to each new point.
#ifdef _USE_ROUGHNESS_MAP
random_center = square_size * temp_map [x1][y1] / 84;
#else
random_center = square_size * 2;
#endif
random_range = random_center * 2;
#ifdef _BIZARRE_ALT_MAP
p1 += ( random ( random_range ) - random_center + p1/4 );
p2 += ( random ( random_range ) - random_center + p2/4 );
p3 += ( random ( random_range ) - random_center + p3/4 );
p4 += ( random ( random_range ) - random_center + p4/4 );
#else
p1 += ( random ( random_range ) - random_center );
p2 += ( random ( random_range ) - random_center );
p3 += ( random ( random_range ) - random_center );
p4 += ( random ( random_range ) - random_center );
#endif
// Boundary checking
p1 = (p1 < min_alt) ? (min_alt - p1) + min_alt : p1;
p2 = (p2 < min_alt) ? (min_alt - p2) + min_alt : p2;
p3 = (p3 < min_alt) ? (min_alt - p3) + min_alt : p3;
p4 = (p4 < min_alt) ? (min_alt - p4) + min_alt : p4;
#ifdef _BIZARRE_ALT_MAP
p1 = (p1 > max_alt) ? (p1 - (max_alt+1)) : p1;
p2 = (p2 > max_alt) ? (p2 - (max_alt+1)) : p2;
p3 = (p3 > max_alt) ? (p3 - (max_alt+1)) : p3;
p4 = (p4 > max_alt) ? (p4 - (max_alt+1)) : p4;
#else
p1 = (p1 > max_alt) ? (max_alt - p1) + max_alt : p1;
p2 = (p2 > max_alt) ? (max_alt - p2) + max_alt : p2;
p3 = (p3 > max_alt) ? (max_alt - p3) + max_alt : p3;
p4 = (p4 > max_alt) ? (max_alt - p4) + max_alt : p4;
#endif
// Write out the generated points.
x2 = (x1 + square_size/2) & clip_mask_x;
y2 = (y1 + square_size/2) & clip_mask_y;
if ( which == 0 ){
alt_map [x1][y1] = (unsigned char) p1;
alt_map [x2][y1] = (unsigned char) p2;
alt_map [x1][y2] = (unsigned char) p3;
alt_map [x2][y2] = (unsigned char) p4;
} else{
color_map [x1][y1] = (unsigned char) p1;
color_map [x2][y1] = (unsigned char) p2;
color_map [x1][y2] = (unsigned char) p3;
color_map [x2][y2] = (unsigned char) p4;
}
counter += 100;
}
{
int percent_done = (int) ( counter / 87360 );
printf ( "\b\b\b\b\b%3d %%", percent_done );
}
}
which = (which == 0) ? 1 : 0;
}
if ( which == 0 ){
memcpy ( alt_map, color_map, map_size_x * map_size_y );
}
// Create some man-made features in the landscape.
flat_area ( 0, 0, 20, 20,0 );
quonset_hut ( 0, 20, 24 );
// We're done!
printf ( "\b\b\b\b\bdone \n" );
fflush ( stdout );
}
//----------------------------------------------------------------------------
// FUNCTION calc_color_map
//----------------------------------------------------------------------------
static void calc_color_map( void)
{
int x, y;
int color;
int percent_done;
int * shadow;
shadow = (int *) calloc ( map_size_y, sizeof (int) );
ASSERT ( shadow != NULL );
printf ( " Shading map: 0 %%" );
fflush ( stdout );
for ( x = 0; x < map_size_x; ++ x ) {
for ( y = 0; y < map_size_y; ++ y ) {
int slope = alt_map [x][y] - alt_map [(x-1)&clip_mask_x][y];
slope *= 2;
slope += 40;
if ( slope < 0 ) slope = 0;
if ( slope > 63 ) slope = 63;
color = slope + 1;
color_map [x][y] = (unsigned char) color;
}
percent_done = x * 24 / map_size_x;
printf ( "\b\b\b\b\b%3d %%", percent_done );
}
// Cast shadows.
for ( y = 0; y < map_size_y; ++ y ) {
shadow [y] = (int) alt_map [0][y];
}
for ( x = 1; x < map_size_x; ++ x ) {
for ( y = 0; y < map_size_y; ++ y ) {
int height;
shadow [y] -= 3;
if ( shadow [y] < 0 ) shadow [y] = 0;
height = (int) alt_map [x][y];
if ( height >= shadow [y] ) {
shadow [y] = height;
temp_map [x][y] = 0;
} else {
temp_map [x][y] = 1;
}
}
percent_done = x * 23 / map_size_x + 24;
printf ( "\b\b\b\b\b%3d %%", percent_done );
}
for ( x = 0; x < 128; ++ x ) {
for ( y = 0; y < map_size_y; ++ y ) {
int height;
shadow [y] -= 3;
if ( shadow [y] < 0 ) shadow [y] = 0;
height = (int) alt_map [x][y];
if ( height >= shadow [y] ){
shadow [y] = height;
temp_map [x][y] = 0;
} else {
temp_map [x][y] = 1;
}
}
percent_done = x * 6 / map_size_x + 47;
printf ( "\b\b\b\b\b%3d %%", percent_done );
}
for ( x = 0; x < map_size_x; ++ x ){
for ( y = 0; y < map_size_y; ++ y ){
if ( temp_map [x][y] ){
int color = (int) color_map [x][y];
color -= 18;
if ( color < 1 )
color = 1;
color_map [x][y] = (unsigned char) color;
}
}
percent_done = x * 23 / map_size_x + 53;
printf ( "\b\b\b\b\b%3d %%", percent_done );
}
// Average the map colors to make the map appear smoother.
for ( x = 0; x < map_size_x; ++ x ){
for ( y = 0; y < map_size_y; ++ y ){
color = 6 * color_map [x][y];
color += 4 * color_map [(x+1) & clip_mask_x][y];
color += 4 * color_map [x][(y+1) & clip_mask_y];
color += 2 * color_map [(x+1) & clip_mask_x][(y+1) & clip_mask_y];
color /= 16;
color_map [x][y] = (unsigned char) color;
}
percent_done = x * 24 / map_size_x + 76;
printf ( "\b\b\b\b\b%3d %%", percent_done );
}
free (shadow);
printf ( "\b\b\b\b\bdone \n" );
fflush ( stdout );
}
//----------------------------------------------------------------------------
// FUNCTION WORLD_generate
//----------------------------------------------------------------------------
void WORLD_generate (void )
{
printf ( "\nGenerating the moonscape...\n\n" );
randomize ();
generate_alt_map ();
calc_color_map ();
}